;; The following macro was suggested by Mark H. Weaver on the Guile Scheme user mailing list, as a
;; response to a different formulation of Chris Vine, also on the Guile Scheme user mailing list.

;; Comments added by me.

(define-syntax pipe-right
  ;; We are not defining any literals.
  (syntax-rules ()
    ;; Base case. If there is only the initial expression, it means, that no operations are applied,
    ;; so the expression is already the result of the pipe.
    [(-> exp) exp]
    ;; If there is an arbitrary number of expressions `exp ...` followed by one final expression
    ;; `(op args ...)`, which consists of an operation `op` and an arbitrary number of arguments
    ;; `args ...` for that operation, ...
    [(-> exp ... (op args ...))
     ;; ... we destrcuture the final operation into the operation name `op` and its arguments `args
     ;; ...`. With that we are able to make it the outer-most wrapping operation call in the syntax
     ;; produced by the macro. Furthermore we output a new macro call, which is the same, except,
     ;; that it is wrapped inside the last operation and does not contain the last operation any
     ;; longer, reducing the number of expressions in the macro call. When the macro is called
     ;; again, it will have another expression as the final operation. This will continue until all
     ;; expressions have been wrapped as procedure calls around the initial expression and the macro
     ;; will go into the base case.
     (op args ... (-> exp ...))]))

;; From this we can easily derive a version `pipe-left`, which always puts the value of the previous
;; pipe step on the left, instead of the right of given arguments to the operations as follows:

(define-syntax pipe-left
  (syntax-rules ()
    [(-> exp) exp]
    [(-> exp ... (op args ...))
     (op (-> exp ...) args ...)]))
